# coding=utf-8
import asyncio

from base import functor, sg


import schedule



last_month = None

@sg.singleton
class TimerMgr(sg.SingletonBase["TimerMgr"]):
	def __init__(self):
		self.time_dict = {}
		self.time_add = 0
	
	async def start_loop(self):
		asyncio.ensure_future(self.loop())
	
	def add_timer(self, obj, func_name, dt, isLoop=False, *args):
		callTime = self.time_add + dt
		
		obj_dict = self.time_dict.get(callTime, None)
		if obj_dict is None:
			obj_dict = {}
			self.time_dict[callTime] = obj_dict
		func_obj_list = obj_dict.get(obj, None)
		if func_obj_list is None:
			func_obj_list = []
			obj_dict[obj] = func_obj_list
		func_obj_list.append({
			"isLoop": isLoop,
			"func_name": func_name,
			"dt": dt,
			"args": args
		})
	
	async def run_timer(self):
		nowTime = self.time_add
		obj_dict = self.time_dict.get(nowTime, None)
		if obj_dict is None:
			return
		
		for obj in obj_dict:
			func_obj_list = obj_dict.get(obj, None)
			if func_obj_list is None:
				continue
			for func_obj in func_obj_list:
				await self.run_func(obj, func_obj)
		
		self.time_dict.pop(nowTime, None)
	
	async def run_func(self, obj, func_obj):
		if func_obj["args"] is not None and len(func_obj["args"]) > 0:
			await functor.Functor(obj, func_obj["func_name"])(func_obj["args"])
		else:
			await functor.Functor(obj, func_obj["func_name"])()
		
		if func_obj["isLoop"]:
			if func_obj["args"] is not None and len(func_obj["args"]) > 0:
				self.add_timer(obj, func_obj["func_name"], func_obj["dt"], func_obj["isLoop"], *func_obj["args"])
			else:
				self.add_timer(obj, func_obj["func_name"], func_obj["dt"], func_obj["isLoop"])
	
	async def loop(self):
		while True:
			await asyncio.sleep(1)
			try:
				await self.run_timer()
			except:
				pass
			schedule.run_pending()
			self.time_add += 1
